package com.se.server;

import com.se.aiClient.AIClient;
import com.se.common.*;
import com.se.db.DbUserInformation;
import com.se.db.DbUtils;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;


/**
 * 服务器配置工具类 - 负责加载服务器端配置信息
 */
public class ServerUtils {
    private static final Properties properties = new Properties();
    public static int port;
    private static final Logger logger = LoggerFactory.getLogger(ServerUtils.class);
    private static final AIClient aiClient = new AIClient();
    private static final ConcurrentHashMap<String, FileMessage>
            fileMessages = new ConcurrentHashMap<>();
    public static final Pattern AT_PATTERN = Pattern.compile("\\s(@\\S+)\\s");

    /*
      静态初始化块 - 在类加载时自动执行配置加载
     */
    static {
        // try-with-resources自动关闭输入流
        try(InputStream input = ServerUtils.class.getResourceAsStream("/server.properties")){
            properties.load(input);
            port = Integer.parseInt(properties.getProperty("server.port"));
        } catch (IOException e) {
            logger.error("读取用户配置失败: {}", e.getMessage(), e);
        }
    }

    /**
     * 私有构造函数 - 防止工具类被实例化
     */
    private ServerUtils(){
    }

    public static AIClient getAiClient() {
        return aiClient;
    }

    public static JSONObject parseUserInfo(String userinfo){
        return new JSONObject(userinfo);
    }

    public static void sendMessage (Socket socket, Message message) {
        try {
            ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
            oos.writeObject(message);
        } catch (IOException e) {
            logger.info("发送消息时出现异常: {}", e.getMessage(), e);
        }
        logger.info("发送信息: {}", message.getMsgType());
    }

    public static void broadcast(Message message) {
        for(String i : OnlineUserManager.getInstance().getOnlineUsers()) {
            Socket socket = Server.getBaseSocket(i);
            if(socket == null) {
                continue;
            }
            sendMessage(socket, message);
        }
    }

    public static void onlineBroadCast(User user) throws SQLException {

        UserInformation information = DbUserInformation.getInstance().get(user.getUserName());

        for(String i : information.getFriendList()) {
            Socket socket = Server.getBaseSocket(i);
            if(socket == null) {
                continue;
            }
            Message message = new Message();
            user.setNotify(user.getNotifyList().contains(i));
            message.setMsgType(MessageType.MESSAGE_USER_LIST_UPDATE);
            message.setContent(user.toString());
            sendMessage(socket, message);
        }
    }

    public static List<Message> mergeAndSortByTime(List<Message> list1, List<Message> list2) {
        List<Message> mergeList = new ArrayList<>();
        mergeList.addAll(list1);
        mergeList.addAll(list2);

        mergeList.sort(Comparator.comparing(m ->
                LocalDateTime.parse(m.getSendTime(), DbUtils.formatter)
        ));

        return mergeList;
    }

    public static Path getProjectRoot() {
        String currentDir = System.getProperty("user.dir");
        Path currentPath = Paths.get(currentDir);

        if(currentPath.endsWith("target")) {
            return currentPath.getParent();
        }
        else {
            return currentPath;
        }
    }

    public static void addFile(String id, FileMessage fileMessage) {
        fileMessages.put(id, fileMessage);
        Path root = getProjectRoot();
        Path serverFileDir = root.resolve("files");
        try {
            Files.createDirectories(serverFileDir);
        } catch (IOException e) {
            logger.info("添加文件夹异常: {}", e.getMessage(), e);
        }

        Path filePath = serverFileDir.resolve(fileMessage.getFileName());

        new Thread(() -> {
            try(FileOutputStream fos = new FileOutputStream(filePath.toString())) {
                fos.write(fileMessage.getFileContent());
            } catch (Exception e) {
                logger.info("添加文件异常: {}", e.getMessage(), e);
            }
        }).start();
    }

    public static FileMessage getFile(String id, Message fileMessage) {
        if(fileMessages.get(id) != null) {
            return fileMessages.get(id);
        }
        FileMessage file = new FileMessage();
        file.setFileMessage(fileMessage);
        file.setMsgType(fileMessage.getMsgType());
        file.setContent(fileMessage.getContent());
        Path root = getProjectRoot();
        logger.info(file.getContent());
        logger.info(file.getFileName());
        Path filePath = root.resolve("files").resolve(file.getFileName());

        file.load(filePath.toString());

        return file;
    }
}
